--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
docs/meshchatx_linux_sandbox.md v4.7.0-rc.6 (b465eab5) Text, 6.61 KB
MeshChatX on Linux: Firejail and Bubblewrap
This page shows how to run T383838meshchatx under Firejail or Bubblewrap (T383838bwrap) on Linux. The legacy CLI name T383838meshchat installs the same entry point and can be substituted in these examples. Use this when you install MeshChatX natively (wheel, package, or Poetry) and want an extra layer of filesystem and process isolation compared to running the binary directly.
These tools do not replace a full virtual machine or hardware-enforced boundary. They reduce exposure of your home directory and other paths the process can write to, when you configure them with tight whitelists or bind mounts.
Containers: If you already run MeshChatX with Docker or Podman, that is a different isolation model; this document is aimed at host-installed T383838meshchatx (or T383838meshchat).
Prerequisites
Install one or both from your distribution:
• Firejail: package name is usually T383838firejail.
• Bubblewrap: package name is usually T383838bubblewrap; the binary is T383838bwrap.
You need a working T383838meshchatx on your T383838PATH (for example after T383838pipx install, T383838pip install --user, or a distro package). The T383838meshchat command is the same binary if both entry points are installed.
Pick a dedicated data directory for sandboxed runs so you do not mix permissions or policies with a non-sandboxed install. The examples below use:
T282828
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Adjust paths if you prefer another location.
Firejail
Firejail applies a profile (or defaults) on top of your command. For MeshChatX you typically want:
• Network left available so Reticulum and the web UI can work (do not use T383838--net=none unless you know you need it).
• Writable only your chosen data directory (and anything else the app truly needs).
Installed T383838meshchatx (pip, pipx, or system package)
T282828
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
firejail --quiet Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
meshchatx --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
If the default profile blocks something MeshChatX needs, you can start from a looser base and tighten later, for example:
T282828
firejail --noprofile --whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
meshchatx --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
T383838--noprofile disables many Firejail restrictions; treat it as a stepping stone, not the final hardening.
From source with UV
Poetry needs the project tree and the virtualenv. Example:
T282828
Tffa657cd /path/to/reticulum-meshchatX
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
Te6edf3VENVTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff/.venvTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
firejail --quiet Tffea00\
--whitelistTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff" Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$VENVTa5d6ff" Tffea00\
--whitelistTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
uv run python -m meshchatx.meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
You may need extra T383838--whitelist= entries if UV or dependencies read config elsewhere (for example under T383838$HOME/.config).
USB serial (RNode or similar)
If Reticulum talks to a radio over a serial device, Firejail may need explicit access to TTY devices, for example:
T282828
firejail --noblacklistTff7b72=/dev/ttyACM0 --noblacklistTff7b72=/dev/ttyUSB0 Tffea00\
...
Use the device nodes your system actually exposes (T383838dmesg, T383838ls /dev/tty*).
Bubblewrap (T383838bwrap)
Bubblewrap does not ship profiles; you list every mount and option. The pattern below keeps the whole root filesystem read-only, mounts a writable tmpfs on T383838/tmp, and makes only your data directory writable at its normal path. Network namespaces are not changed, so Reticulum and TCP/UDP behave like an unsandboxed process unless you add T383838--unshare-net (which usually breaks mesh networking).
Installed T383838meshchatx
T282828
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Tffa657exec bwrap Tffea00\
--die-with-parent Tffea00\
--new-session Tffea00\
--proc /proc Tffea00\
--dev /dev Tffea00\
--ro-bind / / Tffea00\
--tmpfs /tmp Tffea00\
--bind Ta5d6ff"Te6edf3$DATATa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
--uid Ta5d6ff"Tff7b72$(id -uTff7b72)Ta5d6ff" --gid Ta5d6ff"Tff7b72$(id -gTff7b72)Ta5d6ff" Tffea00\
meshchatx --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Notes:
• If T383838meshchatx lives only inside a venv that is not under T383838$DATA, the read-only root still allows reading that path; you do not have to bind-mount the venv separately unless you also need writes there.
• Distributions that merge T383838/ and T383838/usr (merged-usr) still work with T383838--ro-bind / / on typical glibc setups. If T383838bwrap fails with missing library paths, add the extra T383838--ro-bind lines your distro documents (for example T383838/lib64).
From source with UV
Bind the repository and the UV venv read-only, and keep T383838DATA writable:
T282828
Tffa657cd /path/to/reticulum-meshchatX
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/meshchatx-sandboxTa5d6ff"
Te6edf3VENVTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff/.venvTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
Te6edf3PROJTff7b72=Ta5d6ff"Tff7b72$(Tffa657pwdTff7b72)Ta5d6ff"
Tffa657exec bwrap Tffea00\
--die-with-parent Tffea00\
--new-session Tffea00\
--proc /proc Tffea00\
--dev /dev Tffea00\
--ro-bind / / Tffea00\
--tmpfs /tmp Tffea00\
--bind Ta5d6ff"Te6edf3$DATATa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
--ro-bind Ta5d6ff"Te6edf3$PROJTa5d6ff" Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
--ro-bind Ta5d6ff"Te6edf3$VENVTa5d6ff" Ta5d6ff"Te6edf3$VENVTa5d6ff" Tffea00\
--uid Ta5d6ff"Tff7b72$(id -uTff7b72)Ta5d6ff" --gid Ta5d6ff"Tff7b72$(id -gTff7b72)Ta5d6ff" Tffea00\
--setenv PATH Ta5d6ff"Te6edf3$VENVTa5d6ff/bin:Te6edf3$PATHTa5d6ff" Tffea00\
--chdir Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
uv run python -m meshchatx.meshchat --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
T383838uv itself must be reachable on T383838PATH inside the sandbox (often under T383838/usr or T383838$HOME/.local/bin, both visible with T383838--ro-bind / /). If T383838uv run fails because it cannot read T383838~/.cache/uv, add a read-only bind for that directory or invoke the venv interpreter directly instead of T383838uv run:
T282828
Tffa657exec bwrap Tffea00\
... same mounts as above ... Tffea00\
--setenv PATH Ta5d6ff"Te6edf3$VENVTa5d6ff/bin:Te6edf3$PATHTa5d6ff" Tffea00\
--chdir Ta5d6ff"Te6edf3$PROJTa5d6ff" Tffea00\
meshchatx --headless --host T79c0ff127.0.0.1 Tffea00\
--storage-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/storageTa5d6ff" Tffea00\
--reticulum-config-dirTff7b72=Ta5d6ff"Te6edf3$DATATa5d6ff/.reticulumTa5d6ff"
(Use the T383838meshchatx script, the legacy T383838meshchat alias, or T383838python -m entry point from T383838$VENV/bin if your install exposes it there.)
USB serial under Bubblewrap
You may need a clearer view of devices than the minimal T383838--dev /dev provides. Options include T383838--dev-bind /dev /dev (broader device exposure) or binding only the specific character device. Balance convenience against attack surface.
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────